#ifndef __MCS__VARIABLE__HPP
#define __MCS__VARIABLE__HPP

#include "Expression.hpp"
#include "TypeMismatchException.hpp"
#include "Block.hpp"

/// Declaration and run-time instance of the local variable
class Variable : public Object
{
public:
	Variable(SourceLocation const & location, String const & name, ptr<Expression> initializer)
		: location_(location), parentBlock_()
		, dataType_(Value::Null), name_(name)
		, initializer_(initializer), value_()
	{}

	void init(Value::DataType type, Block * parentBlock)
	{
		initializer_->init(parentBlock);
		if(initializer_->dataType() != type)
		{
			throw TypeMismatchExcepion(initializer_->dataType(), type, location());
		}
		dataType_ = type; parentBlock_ = parentBlock;
		parentBlock_->registerVariableDeclaration(this);
	}

	SourceLocation const & location() const { return location_; }
	
	String name() const { return name_; }
	Value::DataType dataType() const { return dataType_; }
	
	ptr<Value> value() const { return value_; }
	void setValue(ptr<Value> const & val) { value_ = val; }
	
	bool exists() const { return value_; }
	
	void create()
	{
		value_ = initializer_->evaluate();
		parentBlock_->registerVariableForCleanup(this);
	}
	
	void destroy() { value_ = ptr<Value>(); }
private:
	SourceLocation location_;
	Block * parentBlock_;
	Value::DataType dataType_;
	String name_;
	ptr<Expression> initializer_;
	ptr<Value> value_;
};

#endif //__MCS__VARIABLE__HPP
